package com.babel.util.tools;

import com.google.common.collect.Maps;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;


public class FormulaTools {

	/**
	 * 合同金额 计算公式：合同金额=申请金额/1-担保费率-信息服务费率
	 * 
	 * @param applyMoney
	 * @param guaranteeRate
	 * @param InterestRate
	 * @return
	 */
	public static BigDecimal computeContractAmount(BigDecimal applyMoney, BigDecimal guaranteeRate,
			BigDecimal InterestRate) {
		BigDecimal sub = new BigDecimal("1").subtract(guaranteeRate).subtract(InterestRate);
		BigDecimal cca = applyMoney.divide(sub,0, BigDecimal.ROUND_HALF_UP);
		BigDecimal result = new BigDecimal(cca.intValue()).divide(new BigDecimal("100"), 0, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
		return result;
	}


	/**
	 * 借款人逾期率 计算公式： 借款利率*2
	 * 
	 * @param applyMoney
	 * @param guaranteeRate
	 * @param InterestRate
	 * @return
	 */
	public static BigDecimal getOverdueRate(BigDecimal debtRate) {
		MathContext mc = new MathContext(2, RoundingMode.HALF_UP);
		return debtRate.multiply(new BigDecimal("2"), mc);
	}

	/**
	 * 每期罚息 计算公式： 应还本息*逾期天数*逾期利率
	 * 
	 * @param applyMoney
	 * @param guaranteeRate
	 * @param InterestRate
	 * @return
	 */
	public static BigDecimal eachLateCharge(BigDecimal money, int days, BigDecimal rate) {

		return money.multiply(new BigDecimal(String.valueOf(days))).multiply(rate).divide(new BigDecimal("365"), 2,BigDecimal.ROUND_HALF_UP);
	}

	/**
	 * 计算两个日期之间相差的天数(yyyy-MM-dd)
	 * 
	 * @param smdate
	 *            较小的时间
	 * @param bdate
	 *            较大的时间
	 * @return 相差天数
	 * @throws ParseException
	 */
	public static int byTwoDateBetweenGetDays(Date smdate, Date bdate) throws ParseException {
		long betweenDays = betweenGetLong(smdate, bdate, "yyyy-MM-dd")/ (1000 * 3600 * 24);
		return Integer.parseInt(String.valueOf(betweenDays));
	}

	/**
	 * 计算两个日期之间相差的小时数(yyyy-MM-dd HH:mm)
	 * 
	 * @param smdate
	 *            较小的时间
	 * @param bdate
	 *            较大的时间
	 * @return 相差天数
	 * @throws ParseException
	 */
	public static int betweenGetHours(Date smdate, Date bdate) throws ParseException {
		long betweenDays = betweenGetLong(smdate, bdate,"yyyy-MM-dd HH:mm") / (1000 * 3600);
		return Integer.parseInt(String.valueOf(betweenDays));
	}
	
	/**
	 * 计算两个日期之间相差的毫秒数
	 * @param smdate
	 * @param bdate
	 * @param format 自定义格式("yyyy-MM-dd HH:mm:ss")
	 * @return
	 * @throws ParseException 
	 */
	public static Long betweenGetLong(Date smdate, Date bdate,String format) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		smdate = sdf.parse(sdf.format(smdate));
		bdate = sdf.parse(sdf.format(bdate));
		Calendar cal = Calendar.getInstance();
		cal.setTime(smdate);
		long time1 = cal.getTimeInMillis();
		cal.setTime(bdate);
		long time2 = cal.getTimeInMillis();
		long betweenDays = (time2 - time1);
		return betweenDays;
	}

	/**
	 * 计算本息方法
	 * 
	 * @param principalMonth
	 * @param interestMonth
	 * @return
	 */
	public static BigDecimal summation(BigDecimal principalMonth, BigDecimal interestMonth) {

		return principalMonth.add(interestMonth);
	}

	/**
	 * 求和方法
	 * 
	 * @param principalMonth
	 * @param interestMonth
	 * @return
	 */
	public static BigDecimal sum(BigDecimal... args) {
		BigDecimal sum = new BigDecimal("0");
		for (BigDecimal arg : args) {
			sum = sum.add(arg);
		}
		return sum;
	}

	/**
	 * 担保费 = 担保费率 * 合同金额
	 * 
	 * @param rate
	 * @param contract
	 * @return
	 */
	public static BigDecimal guaranteeFee(BigDecimal rate, BigDecimal contract) {
		return contract.multiply(rate).setScale(2, RoundingMode.HALF_UP);
	}

	/**
	 * 本期未垫付逾期滞纳金 = 应垫付金额 - 已垫付金额 应垫付金额 BigDecimal sAdvanceAmount 已垫付金额
	 * BigDecimal advancedAmount 本期未垫付逾期滞纳金 BigDecimal nAdvanceAmount
	 * 
	 * @return
	 */
	public static BigDecimal noAdvance(BigDecimal advanceAmount, BigDecimal advancedAmount) {
		return advanceAmount.subtract(advancedAmount);
	}

	/**
	 * 信息服务费 = 合同金额 * 信息服务费率
	 * 
	 * @param contractAmount
	 * @param informationAdminRate
	 * @return
	 */
	public static BigDecimal informationAdminFee(BigDecimal contractAmount, BigDecimal informationAdminRate) {
		return contractAmount.multiply(informationAdminRate).setScale(2, RoundingMode.HALF_UP);
	}
	/**
	 * 去掉时分秒
	 * @param date
	 * @return
	 */
	public static Date getFormatDateTime(Date date,String prm) {
		SimpleDateFormat sdf = new SimpleDateFormat(prm);
		String s = sdf.format(date);
		Date d;
		try {
			d = sdf.parse(s);
			return d;
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 以天为单位 计算日期
	 * @param date
	 * @param num
	 * @return
	 */
	public static Date getNextDay(Date date, int num) {
		Calendar ca = Calendar.getInstance();
		ca.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
		ca.setTime(date);

		int day = ca.get(Calendar.DATE);
		day = day + num;
		ca.set(Calendar.DATE, day);
		
		return ca.getTime();
	}
	/**
	 * 每月还款
	 * 
	 * @return
	 */
	public static BigDecimal monthsRepayment(BigDecimal mRepayment, BigDecimal platformAdminFee) {

		return mRepayment.add(platformAdminFee);
	}

	/**
	 * 平台管理费 = 合同金额*平台管理费率
	 * 
	 * @param platformAdminRate
	 * @param contractAmount
	 * @return
	 */
	public static BigDecimal platformAdminFee(BigDecimal platformAdminRate, BigDecimal contractAmount) {

		return contractAmount.multiply(platformAdminRate).setScale(2, RoundingMode.HALF_UP);
	}

	/**
	 * 接受手机端费率参数 必用方法 费率=(费率参数/100)
	 * 
	 * @param rate
	 * @return
	 */
	public static BigDecimal mobileParm(String rate) {
		return new BigDecimal(rate).divide(new BigDecimal("100"));
	}
	

	/**
	 * 计算月薪收入    月薪收入=（年薪收入/12）
	 */
	public static BigDecimal MonthlyIncome(String jobAnnualIncome){
		return new  BigDecimal(jobAnnualIncome).divide(new BigDecimal("12"),2, BigDecimal.ROUND_HALF_UP);
	}
	/**
	 *计算 尽调通过率=众保笔数÷总抢单量╳100%
	 *众保笔数   Integer dajustedSuccess
	 *总抢单量   Integer totalGrab
	 */
	public static BigDecimal adjustedPassRate(Integer dajustedSuccess,Integer totalGrab){
		BigDecimal v1= new BigDecimal(dajustedSuccess);
		BigDecimal v2= new BigDecimal(totalGrab);
		BigDecimal adjustedPassRate1 =v1.divide(v2, 2, BigDecimal.ROUND_HALF_UP);//四舍五入   保留小数点后2位
		System.out.println(adjustedPassRate1);
		return adjustedPassRate1;
	}
	/**
	 * 佣金总额c_amount=成交金额x返佣比例
	 * private BigDecimal turnoverAmount;//成交金额
	 * private BigDecimal cRatio;//返佣比例
	 */
	public static BigDecimal cAmount(BigDecimal turnoverAmount,BigDecimal cRatio){
		BigDecimal cAmount = turnoverAmount.multiply(cRatio.divide(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP));
		return cAmount;
	}

	/**
	 * 平台公用  逾期利率 千分之三
	 */
	public static BigDecimal overdueRate = new BigDecimal("0.003");

	/**
	 * 一天的毫秒数
	 */
	public static BigInteger days = new BigInteger("86400000");
	/**
	 * 一年的毫秒数
	 */
	public static BigInteger years = new BigInteger("31536000000");

	public static final String currentFormatTime = "yyyy-MM-dd HH:mm:ss";

	public static final String currentFormatDay = "yyyy-MM-dd";

	/**
	 * 个人担保收益比例
	 */
	public static final BigDecimal personageGuaranteeEarningsScale = new BigDecimal(0.95);

	/**
	 * 平台服务费收益比例
	 */
	public static final BigDecimal terraceServiceEarningsScale = new BigDecimal(0.05);

	/**
	 * 平台保留小数位
	 */
	public static final Integer terraceRetainDecimalPlace = 8;

	public static final Integer paymentCacheTime = 1000*60;



	/**
	 * 未繳违约滞纳金 = 垫付金额 * 逾期天数 * 逾期利率
	 *  advanceAmount  应垫付金额
	 *  advancedAmount   已垫付金额
	 *  repaymentDate   还款时间
	 *  currentDay      当前时间
	 * @return
	 */
	public static BigDecimal paymentOnAmount(BigDecimal advanceAmount,BigDecimal advancedAmount,Date repaymentDate,Date currentDay) throws ParseException {
		int day = FormulaTools.calculateDaysDifference(repaymentDate,currentDay,days);
		return (advanceAmount.subtract(advancedAmount)).multiply(
				new BigDecimal(day).multiply(overdueRate)).setScale(2,BigDecimal.ROUND_HALF_UP);
	}

	/**
	 * 计算时间相差天数
	 * @param sDate   最小时间
	 * @param bDate   最大时间
	 * @return   最小时间与最大时间相差   天数/年数/月数
	 * @throws ParseException      时间转换异常
	 */
	public static int calculateDaysDifference(Date sDate,Date bDate,BigInteger unit) {
		int day = 0;
		try{
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			BigInteger repaymentSecound = new BigInteger(String.valueOf(sdf.parse(sdf.format(sDate)).getTime()));
			BigInteger currentSecound = new BigInteger(String.valueOf(sdf.parse(sdf.format(bDate)).getTime()));
			day = ((currentSecound.subtract(repaymentSecound)).divide(unit)).intValue();
		}catch(Exception e){
			throw new  RuntimeException("时间转换异常");
		}
		return day;
	}

	/**
	  * 方法描述： 时间加减法  返回计算后的日期
	  * 创建人：   朱光勋
	  * 创建时间：2017/9/14 11:26
	  * 修改人： 
	  * 修改时间：
	  */
	public static Date calculateDaysInfo(int year,int month,int day,int hour,int minute,int second,int millisecond){
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		cal.add(Calendar.YEAR,year);
		cal.add(Calendar.MONTH,month);
		cal.add(Calendar.DAY_OF_MONTH,day);
		cal.add(Calendar.HOUR_OF_DAY,hour);
		cal.add(Calendar.MINUTE,minute);
		cal.add(Calendar.SECOND,second);
		cal.add(Calendar.MILLISECOND,millisecond);
		Date date = cal.getTime();
		return date;
	}

	/**
	  * 方法描述： 计算日期加减
	  * 创建人：   朱光勋
	  * 创建时间：2017/9/14 11:44
	  * 修改人： 
	  * 修改时间：
	  */
	public static Date calculateDateInfo(int year,int month,int day){
		return FormulaTools.calculateDaysInfo(year,month,day,0,0,0,0);
	}

	/**
	  * 方法描述：计算时间加减
	  * 创建人：  朱光勋
	  * 创建时间：2017/9/14 11:47
	  * 修改人： 
	  * 修改时间：
	  */
	public static Date calcurateTimeInfo(int hour,int minute,int second,int milliSecond){
		return FormulaTools.calculateDaysInfo(0,0,0,hour,minute,second,milliSecond);
	}

	/**
	  * 方法描述：将日期转换为字符串
	  * 创建人：  朱光勋
	  * 创建时间：2017/9/14 17:22
	  * 修改人：
	  * 修改时间：
	  */
	public static String getStringDate(Date date,String format){
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(date);
	}

	public static void main(String[] args) throws ParseException {
		/*Date date = calculateDaysInfo(0, 0, -2, 0, 0, 0, 0);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
		System.out.println(sdf.format(date));*/
		
//		BigDecimal t = computeContractAmount(new BigDecimal("8000"),new BigDecimal("0.17"),new BigDecimal("0.04"));
		System.out.println(FormulaTools.getNextDay(new Date(System.currentTimeMillis()),90));
		/*try {
		    String str = "2017-08-15";
		    Date d = new SimpleDateFormat("yyyy-MM-dd").parse(str);
			int t = FormulaTools.byTwoDateBetweenGetDays(d,new Date());
			System.out.print(t+"==================----------");
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	}
	
	/**
	 *担保服务费=合同金额*担保费率
	 * 担保服务费   BigDecimal guaranteeFee
	 * 合同金额      Integer contractAmount
	 * 担保费率      BigDecimal guaranteeRate
	 *  */
	public static BigDecimal guaranteeFee(Integer contractAmount,BigDecimal guaranteeRate){
		BigDecimal guaranteeFee = new BigDecimal(contractAmount).multiply(guaranteeRate);
		return guaranteeFee;
	}
	
	/**
	 *信息服务费计算（合同金额-借款金额-担保服务费）（担保服务费=合同金额*担保费率）
	 * 备注：批复金额判断为不为空，不为空的话  信息服务费计算（合同金额-批复金额-担保服务费）
	 * 信息服务费   BigDecimal informationFee
	 * 合同金额      Integer contractAmount
	 * 借款金额      Integer applyAmount
	 * 担保服务费  BigDecimal guaranteeFee
	 *  */
	public static BigDecimal informationFee(BigDecimal contractAmount,Integer applyAmount,BigDecimal guaranteeFee){
		BigDecimal informationFee = contractAmount.subtract(new BigDecimal(applyAmount)).subtract(guaranteeFee);
		informationFee = informationFee.setScale(2, BigDecimal.ROUND_HALF_UP);
		return informationFee;
	}

	public static int countTowYear(Date sDate,Date bDate){
		BigInteger smailDate = new BigInteger(String.valueOf(sDate.getTime())).divide(years);
		BigInteger bigDate = new BigInteger(String.valueOf(bDate.getTime())).divide(years);
		return (bigDate.subtract(smailDate)).intValue();
	}

	/**
	 * 获取可担保金额
	 * 初始授信金额  已用授信金额  批复金额  最小比例    最大比例
     */
	public static Map<String,BigDecimal> getGuaranteeSection(BigDecimal usableAmount,BigDecimal approvalAmount, BigDecimal min, BigDecimal max) {
		Map<String,BigDecimal> result = Maps.newHashMap();
		if(usableAmount.compareTo(approvalAmount) < 0){
			result.put("min",BigDecimal.ZERO);
			result.put("max",BigDecimal.ZERO);
		}else{
			result.put("min",min.compareTo(BigDecimal.ONE) < 1 ? approvalAmount.multiply(min) : min);
			result.put("max",max.compareTo(BigDecimal.ONE) < 1 ? approvalAmount.multiply(max) : max);
		}
		return result;
	}

	/**
	 *  计算个人担保收益
	 *  合同金额 * 担保费率 * 个人担保金额 / 批复金额
     */
	public static BigDecimal personageGuaranteeEarnings(BigDecimal contractAmount,BigDecimal guaranteeRate,
														BigDecimal sponsorMoney,BigDecimal approvaleAmount,BigDecimal earningsScale){
		return (contractAmount.multiply(guaranteeRate).multiply(sponsorMoney
				.divide(approvaleAmount,8,BigDecimal.ROUND_HALF_UP)).multiply(earningsScale)).setScale(2,BigDecimal.ROUND_HALF_UP);
	}
}
